//
//  HelloWorldScene.m
//  MessangerSkeleton
//
//  Created by User-16 on 4/1/14.
//  Copyright IOTrainingCamp 2014. All rights reserved.
//
// -----------------------------------------------------------------------

#import "GameScene.h"

//cocos
#import "cocos2d.h"
#import "CollisionDelegate.h"

//coordination
#import "Configuration.h"
#import "GamePlay.h"

//navigation
#import "IntroScene.h"
#import "CCDirector.h"
#import "SpeedUpView.h"
#import "AppDelegate.h"

//game characters
#import "MessengerSprite.h"
#import "Rock.h"
#import "Stalaktit.h"
#import "PowerUpSpeedBoost.h"
#import "FinishLine.h"

//background
#import "Background.h"
#import <Social/Social.h>
#import <Accounts/Accounts.h>

#define kSpeedUpViewTag 5

@interface GameScene ()

//main characters
@property MessengerSprite *player;


//helper nodes
@property Background *route;
@property CCNode* background;
@property CCSpriteBatchNode* backgroundBatchNode;
@property CCSpriteBatchNode* batchNode;

@property CollisionDelegate* collisionHandler;

//level definitions
@property NSArray* spawningObjects;
@property NSArray* spawningXCoordinates;
@property NSArray* spawningYCoordinates;
@property int currentSpawningObject;

//timer seconds
@property (nonatomic) CCButton* secondsPassedSinceStartLabel;

//slice detection
@property CGPoint touchBegin;
@property CGPoint touchEnd;

//coordinating objects
@property GamePlay *gamePlay;
@end


@implementation GameScene

#pragma mark - Factory Method for the scene

+ (GameScene *)sceneWithLevel:(int) level
{

    return [[self alloc] initWithLevel:level];
}


- (id)initWithLevel:(int) level
{
    
    self = [super init];
    if (!self) return(nil);

    self.gamePlay = [GamePlay sharedInstance];
    
    [self loadLevel:level];
    
    [self setupGamePlayNodes];
    [self setupPlayer];
    [self setupHUD];
    
    // Enable touch handling on scene node
    self.userInteractionEnabled = YES;
    
    //setup finish line - needed for multiplayer
    //TODO: 50 is the buffer - should depend on framerate - find dependence
    unsigned long finishIndex = [self.spawningObjects count] - 1;
    double levelLength = [(NSNumber*)self.spawningXCoordinates[finishIndex] doubleValue];
    CGPoint spawnCoords = ccp([[CCDirector sharedDirector] viewSize].width + 50 + levelLength, [(NSNumber*)self.spawningYCoordinates[finishIndex] doubleValue]);

    [self spawnObject:self.spawningObjects[[self.spawningObjects count] - 1] atCoordinates:spawnCoords];

    [self.player run];
    
    
	return self;
}




// -----------------------------------------------------------------------
#pragma mark - Enter & Exit
// -----------------------------------------------------------------------

- (void)onEnter
{
    // always call super onEnter first
    [super onEnter];
    TransferSettings* transferedData = [TransferSettings sharedInstance];
    if (transferedData.soundsOn) {
        [[OALSimpleAudio sharedInstance] playEffect:kPreloadEffectStart];
    }
    transferedData.gameEnded = NO;
    
    // In pre-v3, touch enable and scheduleUpdate was called here
    // In v3, touch is enabled by setting userInterActionEnabled for the individual nodes
    // Per frame update is automatically enabled, if update is overridden
    
}

// -----------------------------------------------------------------------

- (void)onExit
{
    // always call super onExit last
    [super onExit];
    [self removeSpeedUpView];
}

// -----------------------------------------------------------------------
#pragma mark - Touch Handler
// -----------------------------------------------------------------------

-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    self.touchBegin = [touch locationInNode:self];
    
}
-(void) touchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
    self.touchEnd = [touch locationInNode:self];
    
    // Eliminating the tap deffect
    double distance =  sqrt(pow(self.touchBegin.x - self.touchEnd.x, 2) + pow(self.touchBegin.y - self.touchEnd.y, 2));
    if(distance < kMinSwipeDistance)
        return;
    
    // computing the angle of the swipe
    float angle = ccpToAngle(ccpSub(self.touchBegin, self.touchEnd)) + M_PI;
    
    // take actions, according to the angle
    if (angle > M_PI + kBlindSpotForUserInteraction && angle < 2*M_PI - kBlindSpotForUserInteraction){
        [self.player slide];
    }
    if (angle > kBlindSpotForUserInteraction && angle < M_PI - kBlindSpotForUserInteraction){
        [self.player jump];
    }

}

// -----------------------------------------------------------------------
#pragma mark - Button Callbacks
// -----------------------------------------------------------------------

- (void)onPauseClicked:(id)sender
{
    [[GamePlay sharedInstance] setPaused:YES];
    if ([[CCDirector sharedDirector] isPaused]){
        [[CCDirector sharedDirector] stopAnimation];
        [[CCDirector sharedDirector] resume];
        [[CCDirector sharedDirector] startAnimation];
    }
    else{
        [[CCDirector sharedDirector] stopAnimation];
        [[CCDirector sharedDirector] pause];
        
        // Show pause alert
        UIAlertView* pausePressed = [[UIAlertView alloc] initWithTitle:kAllertViewPauseTitle message:@"" delegate:self cancelButtonTitle:kAllertViewResumeButtonTitle otherButtonTitles: kAlertViewMenuButtonTitle, nil];
        [pausePressed show];
    }
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if ([alertView.title isEqualToString:kAlertViewDefaultTitle] || [alertView.title isEqualToString:kAllertViewPauseTitle]) {
        [[GamePlay sharedInstance] setPaused:NO];
        SWITCH([alertView buttonTitleAtIndex:buttonIndex]){
            CASE (kAlertViewMenuButtonTitle) {
                [self returnToMenu:self];
                break;
            }
            CASE(kAllertViewResumeButtonTitle) {
                [self onPauseClicked:self];
                break;
            }
            DEFAULT {
                break;
            }
        }
    }
    
}

//return to menu
- (void)returnToMenu:(id)sender
{
    // back to intro scene with transition
    [self onPauseClicked:self];
    [[CCDirector sharedDirector] replaceScene:[IntroScene scene]
                               withTransition:[CCTransition transitionPushWithDirection:CCTransitionDirectionRight duration:1.0f]];
}


#pragma mark - updates
-(void)update:(CCTime)dt {
    
    //update scoring
    [self.secondsPassedSinceStartLabel setTitle:[NSString stringWithFormat:@"%.2f", (self.player.secondsPassedSinceStart)] ];
    
    //spawn the next obstacle defined in level
    while(self.currentSpawningObject < [self.spawningXCoordinates count] - 1 && self.player.distance > [(NSNumber*)self.spawningXCoordinates[self.currentSpawningObject] doubleValue])
    {

         //TODO: 50 is the buffer - should depend on framerate - find dependence
        CGPoint spawnCoords = ccp([[CCDirector sharedDirector] viewSize].width + 50, [(NSNumber*)self.spawningYCoordinates[self.currentSpawningObject] doubleValue]);
        [self spawnObject:self.spawningObjects[self.currentSpawningObject] atCoordinates:spawnCoords];
        self.currentSpawningObject++;
    }
    
    //move the world back
    CGPoint bgVelocity = ccp(-self.player.currentSpeed.x, 0);
    [self.backgroundBatchNode.children enumerateObjectsUsingBlock:^(CCNode* obj, NSUInteger idx, BOOL *stop) {
        obj.physicsBody.velocity = bgVelocity;
    }];
    
    [self.route update:dt andSpeed:self.player.currentSpeed];
    
}


#pragma mark - private methods


//init related
-(void)loadLevel:(int) level
{
    NSString*  resourceName = [NSString stringWithFormat:@"Level%d", level];
    NSString *fullFileName =
    [NSString stringWithFormat:@"%@.plist", resourceName];
    NSString *plistPath;
    // 1: Get the Path to the plist file
    NSString *rootPath =
    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                         NSUserDomainMask, YES) objectAtIndex:0];
    plistPath = [rootPath stringByAppendingPathComponent:fullFileName];
    if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
        plistPath = [[NSBundle mainBundle]
                     pathForResource:resourceName ofType:@"plist"];
    }
    // 2: Read in the plist file
    NSDictionary *plistDictionary =
    [NSDictionary dictionaryWithContentsOfFile:plistPath];
    // 3: If the plistDictionary was null, the file was not found.
    if (plistDictionary == nil) {
        CCLOG(@"Error reading plist: %@.plist", resourceName);
        return; // No Plist Dictionary or file found
    }
    
    self.spawningObjects = [plistDictionary objectForKey:@"spawnObjects"];
    self.spawningXCoordinates = [plistDictionary objectForKey:@"spawnXCoords"];
    self.spawningYCoordinates = [plistDictionary objectForKey:@"spawnYCoords"];
    self.currentSpawningObject = 0;
    
}

-(void) setupGamePlayNodes{
    //add physics
    CCPhysicsNode* physics = [CCPhysicsNode node];
    physics.gravity = CGPointMake(0, 0);
    //physics.debugDraw = YES;
    self.collisionHandler = [[CollisionDelegate alloc] init];
    physics.collisionDelegate = self.collisionHandler;
    [self addChild:physics];
    
    //Set the spritesheets
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:kMessengerSpriteSheetFilename];
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:kOtherSpritesSpriteSheetFilename];
    
    //set background and its batch node
    self.background = [CCNode node];
    self.background.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:0.1 andCenter:ccp(0.1, 0.1)];
    [physics addChild: self.background z:30];
    
    self.batchNode = [CCSpriteBatchNode batchNodeWithFile:kMessengerSpriteSheetImage];
    [physics addChild:self.batchNode z:100];
    
    
    //node containing everything except the player
    self.backgroundBatchNode = [CCSpriteBatchNode batchNodeWithFile:kOtherSpritesSpriteSheetImage];
    [self.background addChild:self.backgroundBatchNode];
    
    //setup the background
    self.route = [[Background  alloc] init];	
    [self.background addChild:self.route z:-1];

}

-(void) setupPlayer
{
    NSLog(@"self.gamePlay.characterType = %d", self.gamePlay.characterType);
    // Add  the player

        self.player = [[MessengerSprite alloc] initWithType:self.gamePlay.characterType];

    self.player.position  = ccp(self.contentSize.width/4,self.contentSize.height/2 + kSelfYOffset);
    self.player.spawnPoint = self.player.position;
    [self.batchNode addChild:self.player z:100];
    
    [self update:0];
}

-(void) setupHUD
{
    CCButton *backButton;
    
    if ( self.gamePlay.gamePosition == GamePlaySingleplayer ){
        // Create a back button for singleplayer
        backButton = [CCButton buttonWithTitle:kSceneButtonTitlePause fontName:kSceneButtonFontNameVerdanaBold fontSize:18.0f];
        [backButton setTarget:self selector:@selector(onPauseClicked:)];
        
    }else{
        // Create a back button for multiplayer
        backButton = [CCButton buttonWithTitle:kSceneButtonTitleMenu fontName:kSceneButtonFontNameVerdanaBold fontSize:18.0f];
        [backButton setTarget:self selector:@selector(returnToMenu:)];
    }
    
    backButton.positionType = CCPositionTypeNormalized;
    backButton.position = ccp(0.85f, 0.95f); // Top Right of screen
    [backButton setColor:KSceneButtonFontColor];
    [self addChild:backButton];
    
    // Mute Button
    CCButton *muteButton = [CCButton buttonWithTitle:kSceneButtonTitleSounds fontName:kSceneButtonFontNameVerdanaBold fontSize:18.0f];
    muteButton.positionType = CCPositionTypeNormalized;
    muteButton.position = ccp(0.15f,0.95f);
    [muteButton setColor:KSceneButtonFontColor];
    [muteButton setTarget:[TransferSettings sharedInstance] selector:@selector(muteSounds)];
    [self addChild:muteButton];
    
    //time score
    self.secondsPassedSinceStartLabel = [CCButton buttonWithTitle:[NSString stringWithFormat:@"%lu", (unsigned long)self.player.secondsPassedSinceStart] fontName:kSceneButtonFontNameVerdanaBold fontSize:18.0f];
    self.secondsPassedSinceStartLabel.enabled = NO;
    self.secondsPassedSinceStartLabel.positionType = CCPositionTypeNormalized;
    self.secondsPassedSinceStartLabel.position = ccp(0.5, 0.95);
    [self.secondsPassedSinceStartLabel setLabelColor:KSceneButtonFontColor forState:CCControlStateDisabled];
    [self addChild:self.secondsPassedSinceStartLabel];
    
    
    //power up speed boost view
    AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    CGRect frame = [[UIScreen mainScreen] bounds];
    frame.origin.x = frame.size.height - 160;
    frame.origin.y = frame.size.width - 40;
    frame.size.width = 150;
    frame.size.height = 30;
    
    //turbo buton
    SpeedUpView* speedView = [[SpeedUpView alloc] initWithFrame:frame];
    speedView.tag = kSpeedUpViewTag;
    speedView.player = self.player;
    [appDel.window.rootViewController.view addSubview:speedView];
}

//gameplay related
-(void)spawnObject:(NSString*) object atCoordinates:(CGPoint) coords
{
    NSLog(@"spawn");
    CCSprite* spawnedObj;
    
    SWITCH (object) {
        CASE (@"rock") {
            spawnedObj = [[Rock alloc] init];
            break;
        }
        CASE(@"stalaktit") {
            spawnedObj = [[Stalaktit alloc] init];
            break;
        }
        CASE(@"powerUpSpeedBoost") {
            spawnedObj = [[PowerUpSpeedBoost alloc] init];
            break;
        }
        CASE(@"finishLine") {
            spawnedObj = [[FinishLine alloc] init];
            break;
        }
        DEFAULT {
            break;
        }
    }
    
    spawnedObj.position = coords;
    [self.backgroundBatchNode addChild: spawnedObj z:100];
}


//exit related
-(void) removeSpeedUpView{
    UIView* speedView = [[[[[[UIApplication sharedApplication] delegate] window] rootViewController] view] viewWithTag:kSpeedUpViewTag];
    [speedView removeFromSuperview];
}

@end
